package edu.northwestern.cbits.purple_robot_manager.activities.probes; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import android.content.Context; import android.content.SharedPreferences.Editor; import android.database.Cursor; import android.graphics.Color; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v7.app.AppCompatActivity; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.MapsInitializer; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.CircleOptions; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import edu.northwestern.cbits.purple_robot_manager.R; import edu.northwestern.cbits.purple_robot_manager.calibration.LocationCalibrationHelper; import edu.northwestern.cbits.purple_robot_manager.db.ProbeValuesProvider; import edu.northwestern.cbits.purple_robot_manager.logging.SanityManager; import edu.northwestern.cbits.purple_robot_manager.probes.builtin.FusedLocationProbe; import edu.northwestern.cbits.purple_robot_manager.probes.builtin.LocationProbe; import edu.northwestern.cbits.purple_robot_manager.probes.builtin.RawLocationProbe; import edu.northwestern.cbits.purple_robot_manager.util.DBSCAN; import edu.northwestern.cbits.purple_robot_manager.util.DBSCAN.Cluster; import edu.northwestern.cbits.purple_robot_manager.util.DBSCAN.Point; public class LocationLabelActivity extends AppCompatActivity { private ArrayList<Cluster> _clusters = new ArrayList<>(); private int _selectedCluster = -1; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.layout_location_label_activity); DBSCAN dbscan = new DBSCAN(this, DBSCAN.DISTANCE, DBSCAN.POPULATION); Cursor cursor = ProbeValuesProvider.getProvider(this).retrieveValues(this, LocationProbe.DB_TABLE, LocationProbe.databaseSchema()); while (cursor.moveToNext()) { dbscan.addPoint(new Point(cursor.getDouble(cursor.getColumnIndex(LocationProbe.LATITUDE_KEY)), cursor .getDouble(cursor.getColumnIndex(LocationProbe.LONGITUDE_KEY)))); } cursor.close(); cursor = ProbeValuesProvider.getProvider(this).retrieveValues(this, RawLocationProbe.DB_TABLE, RawLocationProbe.databaseSchema()); while (cursor.moveToNext()) { dbscan.addPoint(new Point(cursor.getDouble(cursor.getColumnIndex(RawLocationProbe.LATITUDE_KEY)), cursor .getDouble(cursor.getColumnIndex(RawLocationProbe.LONGITUDE_KEY)))); } cursor.close(); cursor = ProbeValuesProvider.getProvider(this).retrieveValues(this, FusedLocationProbe.DB_TABLE, FusedLocationProbe.databaseSchema()); while (cursor.moveToNext()) { dbscan.addPoint(new Point(cursor.getDouble(cursor.getColumnIndex(FusedLocationProbe.LATITUDE_KEY)), cursor .getDouble(cursor.getColumnIndex(FusedLocationProbe.LONGITUDE_KEY)))); } cursor.close(); this._clusters.addAll(dbscan.calculate(this)); Collections.sort(this._clusters, new Comparator<Cluster>() { public int compare(Cluster one, Cluster two) { if (one.population() > two.population()) return -1; else if (one.population() < two.population()) return 1; return 0; } }); MapsInitializer.initialize(this); this.getSupportActionBar().setTitle(R.string.title_location_label); this.getSupportActionBar().setSubtitle(R.string.title_location_desc); this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); Editor e = PreferenceManager.getDefaultSharedPreferences(this).edit(); e.putLong("last_location_calibration", System.currentTimeMillis()); e.commit(); } protected void onResume() { super.onResume(); SupportMapFragment fragment = (SupportMapFragment) this.getSupportFragmentManager().findFragmentById( R.id.map_fragment); final GoogleMap map = fragment.getMap(); for (int i = 0; i < this._clusters.size(); i++) { Cluster cluster = this._clusters.get(i); int color = Color.BLACK; switch (i % 5) { case 0: color = Color.parseColor("#33B5E5"); break; case 1: color = Color.parseColor("#AA66CC"); break; case 2: color = Color.parseColor("#99CC00"); break; case 3: color = Color.parseColor("#FFBB33"); break; case 4: color = Color.parseColor("#FF4444"); break; } for (Point p : cluster.getPoints(20)) { CircleOptions options = new CircleOptions(); options.center(new LatLng(p.x(), p.y())); options.fillColor(color); options.strokeColor(color); options.strokeWidth(20.0f); options.radius(10); map.addCircle(options); } } ListView list = (ListView) this.findViewById(R.id.list_view); this.registerForContextMenu(list); final LocationLabelActivity me = this; ArrayAdapter<Cluster> adapter = new ArrayAdapter<Cluster>(this, R.layout.layout_cluster_row, this._clusters) { public View getView(final int position, View convertView, final ViewGroup parent) { if (convertView == null) { LayoutInflater inflater = (LayoutInflater) me.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.layout_cluster_row, null); } int color = Color.BLACK; switch (position % 5) { case 0: color = Color.parseColor("#33B5E5"); break; case 1: color = Color.parseColor("#AA66CC"); break; case 2: color = Color.parseColor("#99CC00"); break; case 3: color = Color.parseColor("#FFBB33"); break; case 4: color = Color.parseColor("#FF4444"); break; } Cluster c = me._clusters.get(position); View v = convertView.findViewById(R.id.color_indicator); v.setBackgroundColor(color); TextView clusterName = (TextView) convertView.findViewById(R.id.text_cluster_name); TextView clusterDetails = (TextView) convertView.findViewById(R.id.text_cluster_details); String name = c.getName(); if (name == null) name = me.getString(R.string.title_place_unknown); clusterName.setText(name); clusterDetails.setText(me.getString(R.string.title_place_count, c.population())); v.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { Cluster cluster = me._clusters.get(position); double minX = Double.MAX_VALUE; double minY = Double.MAX_VALUE; double maxX = 0 - Double.MAX_VALUE; double maxY = 0 - Double.MAX_VALUE; for (Point p : cluster.getPoints()) { double x = p.x(); double y = p.y(); if (minX > x) minX = x; if (minY > y) minY = y; if (maxX < x) maxX = x; if (maxY < y) maxY = y; } LatLngBounds bounds = new LatLngBounds(new LatLng(minX, minY), new LatLng(maxX, maxY)); map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, parent.getWidth() / 2, parent.getHeight() / 2, 20)); } }); return convertView; } }; if (this._clusters.size() > 0) { Cluster cluster = this._clusters.get(0); double minX = Double.MAX_VALUE; double minY = Double.MAX_VALUE; double maxX = 0 - Double.MAX_VALUE; double maxY = 0 - Double.MAX_VALUE; for (Point p : cluster.getPoints()) { double x = p.x(); double y = p.y(); if (minX > x) minX = x; if (minY > y) minY = y; if (maxX < x) maxX = x; if (maxY < y) maxY = y; } LatLngBounds bounds = new LatLngBounds(new LatLng(minX, minY), new LatLng(maxX, maxY)); map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 20)); } list.setAdapter(adapter); list.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { me._selectedCluster = position; parent.showContextMenu(); } }); } public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.setHeaderTitle(R.string.menu_label_cluster); String[] groups = this.getResources().getStringArray(R.array.place_groups); for (int i = 0; i < groups.length; i++) { String group = groups[i]; menu.add(Menu.NONE, i, i, group); } } public boolean onContextItemSelected(MenuItem item) { Cluster selected = this._clusters.get(this._selectedCluster); selected.setName(item.getTitle().toString()); ListView list = (ListView) this.findViewById(R.id.list_view); list.setAdapter(list.getAdapter()); DBSCAN.persistClusters(this, this._clusters, DBSCAN.DISTANCE, DBSCAN.POPULATION); return true; } protected void onPause() { super.onPause(); LocationCalibrationHelper.check(this); SanityManager.getInstance(this).refreshState(); } public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) this.finish(); return true; } }